package com.tmxk.jdbc02.utils;

import java.sql.*;

/**
 * 操作数据库工具类
 */
public class BaseDao {
    //使用静态常量标识 数据库连接路径、 用户名 、 用户密码
    protected static final String URL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
    protected static final String USERNAME = "scott";
    protected static final String PASSWORD = "scott";
    // 定义公共的数据连接对象、 动态执行sql语句传输通道、 rs结果集
    protected Connection conn = null;
    protected PreparedStatement pstmt = null;
    protected ResultSet rs = null;

    static {
        // 应用了反射机制,使用Class.forName(Driver) 加载数据库驱动
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 建立数据库连接方法
     * @return 数据库连接信息
     */
    public Connection getConnection(){
        try {
            return DriverManager.getConnection(URL,USERNAME,PASSWORD);
        } catch (SQLException throwables) {
            // throwables.printStackTrace();   // 该方式是抛出异常堆栈信息
            System.out.println("数据库连接异常,异常原因为:" + throwables.getMessage());
        }
        return null;
    }

    /**
     *  定义一个公共的释放所有数据连接的方法
     * @param rs         rs结果集
     * @param pstmt     预编译传输sql语句通道
     * @param conn      数据库连接对象
     */
    public void closeAllConn(ResultSet rs, PreparedStatement pstmt , Connection conn){
        // 释放所有资源
        try {
            if( rs != null){
                rs.close();
            }
            if( pstmt!= null ){
                pstmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // Object[] params 参数数组, 该写法 如sql语句中没有参数条件值,需判断该数组是否有值
    // Object...params 可选参数数组, 该写法 如sql语句中没有参数条件值 , 可不进行判断该数组是否有值
    /**
     * 定义一个公共的查询方法
     * @param sql  定义的查询sql语句
     * @param params  可选参数数组,用来接收 条件参数
     * @return
     */
    public ResultSet executeQuery(String sql,Object...params){
        //1. 调用数据库连接方法
        conn =  getConnection();
        try {
            // 3. 建立数据库连接通道, 传输sql语句
            pstmt = conn.prepareStatement(sql);
            for (int i = 0; i < params.length ; i++) {
                //4. 设置预编译sql语句中的动态参数
                pstmt.setObject(i + 1,params[i]);
            }
            // 5. 触发执行sql语句
            rs = pstmt.executeQuery();
        }catch (SQLException e){
            e.printStackTrace();
        }
        return rs;
    }

    /**
     * 定义一个公共的增删改方法
     * @param sql 定义的dml操作语句
     * @param params 可选参数数组,用来接收传递的条件参数
     * @return
     */
    public int executeUpdate(String sql,Object...params){
        //定义一个变量,用来接收受影响的行数
        int result = 0;
        //1.连接数据库
        conn = getConnection();
        try{
            //3. 建立数据库连接通道,传输sql语句
            pstmt = conn.prepareStatement(sql);
            for (int i = 0; i < params.length ; i++) {
                //4.设置预编译sql语句中的动态参数
                pstmt.setObject(i+1, params[i]);
            }
            //5.触发执行sql语句
            result = pstmt.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            closeAllConn(rs,pstmt,conn);
        }
        return result;
    }


}
